from abc import abstractmethod

from ygframe.design_pattern.abstract_builder import AbstractBuilder
from ygframe.util.dict_util import get_dict

__author__ = 'jing'


class ImagePullPolicy:
    IF_NOT_PRESENT = 'IfNotPresent'


class KubeMetaBuilder(AbstractBuilder):
    def name(self, name):
        return self.deep_update(metadata=dict(name=name))

    def label(self, *args, **kwargs):
        return self.deep_update(metadata=dict(labels=get_dict(*args, **kwargs)))

    def spec(self, spec):
        return self.deep_update(spec)


class KubeResourceBuilder(KubeMetaBuilder):

    def __init__(self) -> None:
        self.get_type()

    @abstractmethod
    def get_type(self):
        raise NotImplementedError

    def api_version(self, version='v1'):
        return self.update(apiVersion=version)

    def kind(self, kind):
        return self.update(kind=kind)


class RcBuilder(KubeResourceBuilder):
    def get_type(self):
        return self.api_version('v1').kind('ReplicationController')

    def replicas(self, replicas=1):
        return self.deep_update(spec=dict(replicas=replicas))

    def selector(self, *args, **kwargs):
        return self.deep_update(spec=dict(selector=get_dict(*args, **kwargs)))

    def template(self, tmp):
        return self.deep_update(spec=dict(template=tmp))


class ContainerBuilder(AbstractBuilder):
    def name(self, name):
        return self.update(name=name)

    def limits(self, limits):
        return self.deep_update(resources=dict(limits=limits))

    def requests(self, requests):
        return self.deep_update(resources=dict(requests=requests))

    def image(self, image):
        return self.update(image=image)

    def image_pull_policy(self, image_pull_policy):
        return self.update(image_pull_policy=image_pull_policy)

    def env(self, *args, **kwargs):
        data = get_dict(*args, **kwargs)
        env = []
        for key, value in data.items():
            env.append(dict(name=key, value=value))
        if env:
            return self.deep_update(env=env)
        else:
            return self

    def cmd(self, cmd):
        if cmd:
            return self.deep_update(command=cmd)
        return self

    def privileged(self):
        return self.deep_update(securityContext=dict(privileged=True))

    def port(self, container_port, host_port=None, target_port=None):
        port_data = dict(containerPort=container_port)
        if host_port:
            port_data.update(dict(hostPort=host_port))
        if target_port:
            port_data.update(dict(targetPort=target_port))
        return self.deep_update(ports=[port_data])

    def volume_mount(self, path, name):
        return self.deep_update(volumnMounts=[dict(name=name, mountPath=path)])

    def args(self, args):
        return self.deep_update(args=args)


class TemplateBuilder(KubeMetaBuilder):
    def container(self, container):
        return self.update(spec=dict(containers=[container]))

    def volume_host_path(self, name, path):
        return self.update(spec=dict(volumes=[dict(
            name=name,
            hostPath=dict(path=path)
        )]))
